/*
 * Adpt.h
 *
 */

#ifndef ADPT_H_
#define ADPT_H_

#include <sstream>
#include <vector>
#include <map>
#include "../middleware/MiddlewareCommon.h"

namespace application {

typedef enum{ESTANTE_VACIO=0,EN_PRODUCCION, ESTANTE_LLENO}EstanteStatus;

struct Estante
{
	Estante():ordenCompra(),status(ESTANTE_VACIO),producto()
	{

	};

	virtual ~Estante(){};

	OrdenCompraHeader ordenCompra;
	EstanteStatus status;
	Producto producto;

	std::string serialize()
	{
		std::stringstream ss;

		ss << "|"<< ordenCompra.ordenCompraId<<"|"<<status<<"|"<<producto.tipo<<"|"<<producto.productoId<<"|"<<producto.estado<<"|\n";
		return ss.str();
	}
};

class Adpt
{
public:
	typedef std::list<int>EstanteNumList;
	typedef std::vector<Estante> EstanteCollection;
	struct OrdenCompraTipoProducto
	{
		OrdenCompraHeader ordenCompra;
		ProductoCantidad producto;

//		//Para poderla usar con el map
//		bool operator<( const OrdenCompraTipoProducto &a) const
//		{
//				return (this->ordenCompra.ordenCompraId < a.ordenCompra.ordenCompraId) &&
//						(this->producto < a.producto);
//		}
	};

	typedef std::list<OrdenCompraTipoProducto>OrdenCompraTipoProductoMap;

	static const int ESPACIO_ALMACEN = 10;
public:
	Adpt();
	virtual ~Adpt();

	bool reservarEstantesParaProducto(ProductoCantidad &producto, EstanteNumList &estantes);

	int obtenerCantEstantesVacios();
	int obtenerEstanteVacio();

	int obtenerEstanteProducto(TipoProducto tipo);
	void asignarOCEstantes(EstanteNumList &estantes,
							  const OrdenCompraHeader ordenCompra);

	void almacenarProducto(int estanteId, Producto &producto);
	void retirarProductoEstante(int estanteId, Producto &producto);

	std::string serialize();

	int getCantidadProductosRestantesOC(const TipoProducto producto,const OrdenCompraHeader ordenCompra);

	void getOrdenCompraEstante(int estanteId, OrdenCompraHeader &ordenCompra) const;
	void getProductoCantidad(OrdenCompraHeader &ordenCompra,ProductoCantidad& prodCantidad);

	EstanteNumList buscarProductoSinOC(TipoProducto producto);
	EstanteNumList buscarProductoConOC(OrdenCompraId ordenCompraId, TipoProducto producto);

private:
	void modifyOCTipoProd(OrdenCompraTipoProducto ocTipoProd, int cantidad);
	int getOCTipoProd(OrdenCompraTipoProducto ocTipoProd);

	EstanteCollection m_Estantes;

	EstanteNumList m_EstantesLibresNums;
	OrdenCompraTipoProductoMap m_ordenesCompraCantidades;
	std::map<OrdenCompraHeader,ProductoCantidad> m_ordenesCompraProductos;
};

} /* namespace application */
#endif /* ADPT_H_ */
